home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 25 / CU Amiga Magazine's Super CD-ROM 25 (1998)(EMAP Images)(GB)(Track 1 of 2)[!][issue 1998-08].iso / CUCD / Utilities / Type1Manager / src / scanfont.c < prev    next >
C/C++ Source or Header  |  1996-07-12  |  42KB  |  1,636 lines

  1. /* $XConsortium: scanfont.c,v 1.10 94/02/06 16:23:17 gildea Exp $ */
  2. /* Copyright International Business Machines,Corp. 1991
  3.  * All Rights Reserved
  4.  *
  5.  * License to use, copy, modify, and distribute this software
  6.  * and its documentation for any purpose and without fee is
  7.  * hereby granted, provided that the above copyright notice
  8.  * appear in all copies and that both that copyright notice and
  9.  * this permission notice appear in supporting documentation,
  10.  * and that the name of IBM not be used in advertising or
  11.  * publicity pertaining to distribution of the software without
  12.  * specific, written prior permission.
  13.  *
  14.  * IBM PROVIDES THIS SOFTWARE "AS IS", WITHOUT ANY WARRANTIES
  15.  * OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT
  16.  * LIMITED TO ANY IMPLIED WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT OF
  18.  * THIRD PARTY RIGHTS.  THE ENTIRE RISK AS TO THE QUALITY AND
  19.  * PERFORMANCE OF THE SOFTWARE, INCLUDING ANY DUTY TO SUPPORT
  20.  * OR MAINTAIN, BELONGS TO THE LICENSEE.  SHOULD ANY PORTION OF
  21.  * THE SOFTWARE PROVE DEFECTIVE, THE LICENSEE (NOT IBM) ASSUMES
  22.  * THE ENTIRE COST OF ALL SERVICING, REPAIR AND CORRECTION.  IN
  23.  * NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  24.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
  25.  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
  26.  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  27.  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  28.  * SOFTWARE.
  29.  */
  30. /* Author: Katherine A. Hitchcock    IBM Almaden Research Laboratory */
  31.  
  32. #ifndef T1GST
  33. #include "global.h"
  34. #endif
  35.  
  36. static int rc;
  37. static boolean InPrivateDict;
  38. static boolean WantFontInfo;
  39. static boolean TwoSubrs;
  40. static psobj inputFile;
  41. static psobj filterFile;
  42. static psobj *inputP;
  43.  
  44. /**********************************************************************/
  45. /*   Init_BuiltInEncoding()                                           */
  46. /*                                                                    */
  47. /*     Initializes the StandardEncoding and ISOLatin1Encoding vector. */
  48. /*                                                                    */
  49. /**********************************************************************/
  50. typedef struct            /* Builtin Standard Encoding */
  51. {
  52.     int index;
  53.     char *name;
  54. }
  55. EncodingTable;
  56.  
  57. const static EncodingTable StdEnc[] =
  58. {
  59.     040, "space",
  60.     041, "exclam",
  61.     042, "quotedbl",
  62.     043, "numbersign",
  63.     044, "dollar",
  64.     045, "percent",
  65.     046, "ampersand",
  66.     047, "quoteright",
  67.     050, "parenleft",
  68.     051, "parenright",
  69.     052, "asterisk",
  70.     053, "plus",
  71.     054, "comma",
  72.     055, "hyphen",
  73.     056, "period",
  74.     057, "slash",
  75.     060, "zero",
  76.     061, "one",
  77.     062, "two",
  78.     063, "three",
  79.     064, "four",
  80.     065, "five",
  81.     066, "six",
  82.     067, "seven",
  83.     070, "eight",
  84.     071, "nine",
  85.     072, "colon",
  86.     073, "semicolon",
  87.     074, "less",
  88.     075, "equal",
  89.     076, "greater",
  90.     077, "question",
  91.     0100, "at",
  92.     0101, "A",
  93.     0102, "B",
  94.     0103, "C",
  95.     0104, "D",
  96.     0105, "E",
  97.     0106, "F",
  98.     0107, "G",
  99.     0110, "H",
  100.     0111, "I",
  101.     0112, "J",
  102.     0113, "K",
  103.     0114, "L",
  104.     0115, "M",
  105.     0116, "N",
  106.     0117, "O",
  107.     0120, "P",
  108.     0121, "Q",
  109.     0122, "R",
  110.     0123, "S",
  111.     0124, "T",
  112.     0125, "U",
  113.     0126, "V",
  114.     0127, "W",
  115.     0130, "X",
  116.     0131, "Y",
  117.     0132, "Z",
  118.     0133, "bracketleft",
  119.     0134, "backslash",
  120.     0135, "bracketright",
  121.     0136, "asciicircum",
  122.     0137, "underscore",
  123.     0140, "quoteleft",
  124.     0141, "a",
  125.     0142, "b",
  126.     0143, "c",
  127.     0144, "d",
  128.     0145, "e",
  129.     0146, "f",
  130.     0147, "g",
  131.     0150, "h",
  132.     0151, "i",
  133.     0152, "j",
  134.     0153, "k",
  135.     0154, "l",
  136.     0155, "m",
  137.     0156, "n",
  138.     0157, "o",
  139.     0160, "p",
  140.     0161, "q",
  141.     0162, "r",
  142.     0163, "s",
  143.     0164, "t",
  144.     0165, "u",
  145.     0166, "v",
  146.     0167, "w",
  147.     0170, "x",
  148.     0171, "y",
  149.     0172, "z",
  150.     0173, "braceleft",
  151.     0174, "bar",
  152.     0175, "braceright",
  153.     0176, "asciitilde",
  154.     0241, "exclamdown",
  155.     0242, "cent",
  156.     0243, "sterling",
  157.     0244, "fraction",
  158.     0245, "yen",
  159.     0246, "florin",
  160.     0247, "section",
  161.     0250, "currency",
  162.     0251, "quotesingle",
  163.     0252, "quotedblleft",
  164.     0253, "guillemotleft",
  165.     0254, "guilsinglleft",
  166.     0255, "guilsinglright",
  167.     0256, "fi",
  168.     0257, "fl",
  169.     0261, "endash",
  170.     0262, "dagger",
  171.     0263, "daggerdbl",
  172.     0264, "periodcentered",
  173.     0266, "paragraph",
  174.     0267, "bullet",
  175.     0270, "quotesinglbase",
  176.     0271, "quotedblbase",
  177.     0272, "quotedblright",
  178.     0273, "guillemotright",
  179.     0274, "ellipsis",
  180.     0275, "perthousand",
  181.     0277, "questiondown",
  182.     0301, "grave",
  183.     0302, "acute",
  184.     0303, "circumflex",
  185.     0304, "tilde",
  186.     0305, "macron",
  187.     0306, "breve",
  188.     0307, "dotaccent",
  189.     0310, "dieresis",
  190.     0312, "ring",
  191.     0313, "cedilla",
  192.     0315, "hungarumlaut",
  193.     0316, "ogonek",
  194.     0317, "caron",
  195.     0320, "emdash",
  196.     0341, "AE",
  197.     0343, "ordfeminine",
  198.     0350, "Lslash",
  199.     0351, "Oslash",
  200.     0352, "OE",
  201.     0353, "ordmasculine",
  202.     0361, "ae",
  203.     0365, "dotlessi",
  204.     0370, "lslash",
  205.     0371, "oslash",
  206.     0372, "oe",
  207.     0373, "germandbls",
  208.     0, 0
  209. };
  210.  
  211. const static EncodingTable ISO8859Enc[] =
  212. {
  213.     32, "space",
  214.     33, "exclam",
  215.     34, "quotedbl",
  216.     35, "numbersign",
  217.     36, "dollar",
  218.     37, "percent",
  219.     38, "ampersand",
  220.     39, "quoteright",
  221.     40, "parenleft",
  222.     41, "parenright",
  223.     42, "asterisk",
  224.     43, "plus",
  225.     44, "comma",
  226.     45, "minus",
  227.     46, "period",
  228.     47, "slash",
  229.     48, "zero",
  230.     49, "one",
  231.     50, "two",
  232.     51, "three",
  233.     52, "four",
  234.     53, "five",
  235.     54, "six",
  236.     55, "seven",
  237.     56, "eight",
  238.     57, "nine",
  239.     58, "colon",
  240.     59, "semicolon",
  241.     60, "less",
  242.     61, "equal",
  243.     62, "greater",
  244.     63, "question",
  245.     64, "at",
  246.     65, "A",
  247.     66, "B",
  248.     67, "C",
  249.     68, "D",
  250.     69, "E",
  251.     70, "F",
  252.     71, "G",
  253.     72, "H",
  254.     73, "I",
  255.     74, "J",
  256.     75, "K",
  257.     76, "L",
  258.     77, "M",
  259.     78, "N",
  260.     79, "O",
  261.     80, "P",
  262.     81, "Q",
  263.     82, "R",
  264.     83, "S",
  265.     84, "T",
  266.     85, "U",
  267.     86, "V",
  268.     87, "W",
  269.     88, "X",
  270.     89, "Y",
  271.     90, "Z",
  272.     91, "bracketleft",
  273.     92, "backslash",
  274.     93, "bracketright",
  275.     94, "asciicircum",
  276.     95, "underscore",
  277.     96, "quoteleft",
  278.     97, "a",
  279.     98, "b",
  280.     99, "c",
  281.     100, "d",
  282.     101, "e",
  283.     102, "f",
  284.     103, "g",
  285.     104, "h",
  286.     105, "i",
  287.     106, "j",
  288.     107, "k",
  289.     108, "l",
  290.     109, "m",
  291.     110, "n",
  292.     111, "o",
  293.     112, "p",
  294.     113, "q",
  295.     114, "r",
  296.     115, "s",
  297.     116, "t",
  298.     117, "u",
  299.     118, "v",
  300.     119, "w",
  301.     120, "x",
  302.     121, "y",
  303.     122, "z",
  304.     123, "braceleft",
  305.     124, "bar",
  306.     125, "braceright",
  307.     126, "asciitilde",
  308.     161, "exclamdown",
  309.     162, "cent",
  310.     163, "sterling",
  311.     164, "currency",
  312.     165, "yen",
  313.     166, "brokenbar",
  314.     167, "section",
  315.     168, "dieresis",
  316.     169, "copyright",
  317.     170, "ordfeminine",
  318.     171, "guillemotleft",
  319.     172, "logicalnot",
  320.     173, "hyphen",
  321.     174, "registered",
  322.     175, "macron",
  323.     176, "degree",
  324.     177, "plusminus",
  325.     178, "twosuperior",
  326.     179, "threesuperior",
  327.     180, "acute",
  328.     181, "mu",
  329.     182, "paragraph",
  330.     183, "periodcentered",
  331.     184, "cedilla",
  332.     185, "onesuperior",
  333.     186, "ordmasculine",
  334.     187, "guillemotright",
  335.     188, "onequarter",
  336.     189, "onehalf",
  337.     190, "threequarters",
  338.     191, "questiondown",
  339.     192, "Agrave",
  340.     193, "Aacute",
  341.     194, "Acircumflex",
  342.     195, "Atilde",
  343.     196, "Adieresis",
  344.     197, "Aring",
  345.     198, "AE",
  346.     199, "Ccedilla",
  347.     200, "Egrave",
  348.     201, "Eacute",
  349.     202, "Ecircumflex",
  350.     203, "Edieresis",
  351.     204, "Igrave",
  352.     205, "Iacute",
  353.     206, "Icircumflex",
  354.     207, "Idieresis",
  355.     208, "Eth",
  356.     209, "Ntilde",
  357.     210, "Ograve",
  358.     211, "Oacute",
  359.     212, "Ocircumflex",
  360.     213, "Otilde",
  361.     214, "Odieresis",
  362.     215, "multiply",
  363.     216, "Oslash",
  364.     217, "Ugrave",
  365.     218, "Uacute",
  366.     219, "Ucircumflex",
  367.     220, "Udieresis",
  368.     221, "Yacute",
  369.     222, "Thorn",
  370.     223, "germandbls",
  371.     224, "agrave",
  372.     225, "aacute",
  373.     226, "acircumflex",
  374.     227, "atilde",
  375.     228, "adieresis",
  376.     229, "aring",
  377.     230, "ae",
  378.     231, "ccedilla",
  379.     232, "egrave",
  380.     233, "eacute",
  381.     234, "ecircumflex",
  382.     235, "edieresis",
  383.     236, "igrave",
  384.     237, "iacute",
  385.     238, "icircumflex",
  386.     239, "idieresis",
  387.     240, "eth",
  388.     241, "ntilde",
  389.     242, "ograve",
  390.     243, "oacute",
  391.     244, "ocircumflex",
  392.     245, "otilde",
  393.     246, "odieresis",
  394.     247, "divide",
  395.     248, "oslash",
  396.     249, "ugrave",
  397.     250, "uacute",
  398.     251, "ucircumflex",
  399.     252, "udieresis",
  400.     253, "yacute",
  401.     254, "thorn",
  402.     255, "ydieresis",
  403.     0, 0
  404. };
  405.  
  406. static psobj *StdEncArrayP = NULL;
  407. psobj *ISOLatin1EncArrayP = NULL;
  408.  
  409. static psobj *MakeEncodingArrayP(const EncodingTable *encodingTable);
  410. static int getNextValue(int valueType);
  411. static int getInt(void);
  412. static int getEncoding(psobj *arrayP);
  413. static int getArray(psobj *arrayP);
  414. static int getName(char *nameP);
  415. static int getNbytes(int N);
  416. static int getLiteralName(psobj *nameObjP);
  417. static int BuildSubrs(psfont *FontP);
  418. static int BuildCharStrings(psfont *FontP);
  419. static int BuildFontInfo(psfont *fontP);
  420. static int BuildPrivate(psfont *fontP);
  421. static int GetType1Blues(psfont *fontP);
  422. static int FindDictValue(psdict *dictP);
  423.  
  424.  
  425. static psobj *MakeEncodingArrayP(const EncodingTable *encodingTable)
  426. {
  427.     int i;
  428.     psobj *encodingArrayP;
  429.  
  430.     encodingArrayP = (psobj *) vm_alloc(256 * (sizeof(psobj)));
  431.     if (!encodingArrayP)
  432.         return NULL;
  433.  
  434.     /* initialize everything to .notdef */
  435.     for (i = 0; i < 256; i++)
  436.         objFormatName(&(encodingArrayP[i]), 7, ".notdef");
  437.  
  438.     for (i = 0; encodingTable[i].name; i++)
  439.     {
  440.         objFormatName(&(encodingArrayP[encodingTable[i].index]),
  441.                   strlen(encodingTable[i].name),
  442.                   encodingTable[i].name);
  443.     }
  444.  
  445.     return (encodingArrayP);
  446. }
  447.  
  448. boolean Init_BuiltInEncoding(void)
  449. {
  450.     StdEncArrayP = MakeEncodingArrayP(StdEnc);
  451.     ISOLatin1EncArrayP = MakeEncodingArrayP(ISO8859Enc);
  452.     return (StdEncArrayP && ISOLatin1EncArrayP);
  453. }
  454.  
  455. /********************************************************************/
  456. /***================================================================***/
  457. static int getNextValue(int valueType)
  458. {
  459.     scan_token(inputP);
  460.     if (tokenType != valueType)
  461.     {
  462.         return (SCAN_ERROR);
  463.     }
  464.     return (SCAN_OK);
  465.  
  466. }
  467. /***================================================================***/
  468. /*  This routine will set the global rc if there is an error          */
  469. /***================================================================***/
  470. static int getInt(void)
  471. {
  472.     scan_token(inputP);
  473.     if (tokenType != TOKEN_INTEGER)
  474.     {
  475.         rc = SCAN_ERROR;
  476.         return (0);
  477.     }
  478.     else
  479.     {
  480.         return (tokenValue.integer);
  481.     }
  482.  
  483. }
  484. /***================================================================***/
  485. /*
  486.  * See Sec 10.3 of ``Adobe Type 1 Font Format'' v1.1,
  487.  * for parsing Encoding.
  488.  */
  489. static int getEncoding(psobj *arrayP)
  490. {
  491.  
  492.     scan_token(inputP);
  493.     if ((tokenType == TOKEN_NAME)
  494.         &&
  495.         (((tokenLength == 16) && (!strncmp(tokenStartP, "StandardEncoding", 16))) ||
  496.          (((tokenLength == 17) && (!strncmp(tokenStartP, "ISOLatin1Encoding", 17))))))
  497.     {
  498.         /* Adobe Standard Encoding */
  499. /*
  500.         if (tokenLength == 16)
  501.             arrayP->data.valueP = (char *)StdEncArrayP;
  502.         else
  503.             arrayP->data.valueP = (char *)ISOLatin1EncArrayP;
  504. */
  505. /***
  506.  *** Hack by Amish 2/12/95: Always use ISOLatin1 over of StdEncoding.
  507.  *** Can still use the font's built in encoding however (for Symbol, etc)
  508.  ***/
  509.         arrayP->data.valueP = (char *)ISOLatin1EncArrayP;
  510.  
  511.         arrayP->len = 256;
  512.         return (SCAN_OK);
  513.     }
  514.     else if ((tokenType == TOKEN_LEFT_BRACE) ||
  515.          (tokenType == TOKEN_LEFT_BRACKET))
  516.     {
  517.         /* Array of literal names */
  518.  
  519.         psobj *objP;
  520.         int i;
  521.  
  522.         objP = (psobj *) vm_alloc(256 * (sizeof(psobj)));
  523.         if (!(objP))
  524.             return (SCAN_OUT_OF_MEMORY);
  525.  
  526.         arrayP->data.valueP = (char *)objP;
  527.         arrayP->len = 256;
  528.  
  529.         for (i = 0; i < 256; i++, objP++)
  530.         {
  531.             scan_token(inputP);
  532.  
  533.             if (tokenType != TOKEN_LITERAL_NAME)
  534.                 return (SCAN_ERROR);
  535.  
  536.             if (!(vm_alloc(tokenLength)))
  537.                 return (SCAN_OUT_OF_MEMORY);
  538.  
  539.             objFormatName(objP, tokenLength, tokenStartP);
  540.         }
  541.  
  542.         scan_token(inputP);
  543.         if ((tokenType == TOKEN_RIGHT_BRACE) ||
  544.             (tokenType == TOKEN_RIGHT_BRACKET))
  545.             return (SCAN_OK);
  546.     }
  547.     else
  548.     {
  549.         /* Must be sequences of ``dup <index> <charactername> put" */
  550.  
  551.         psobj *objP;
  552.         int i;
  553.  
  554.         objP = (psobj *) vm_alloc(256 * (sizeof(psobj)));
  555.         if (!(objP))
  556.             return (SCAN_OUT_OF_MEMORY);
  557.  
  558.         arrayP->data.valueP = (char *)objP;
  559.         arrayP->len = 256;
  560.  
  561.         for (i = 0; i < 256; i++)
  562.             objFormatName(objP + i, 7, ".notdef");
  563.  
  564.         while (TRUE)
  565.         {
  566.             scan_token(inputP);
  567.  
  568.             switch (tokenType)
  569.             {
  570.             case TOKEN_NAME:
  571.                 if (tokenLength == 3)
  572.                 {
  573.                     if (strncmp(tokenStartP, "dup", 3) == 0)
  574.                     {
  575.                         /* get <index> */
  576.                         scan_token(inputP);
  577.                         if (tokenType != TOKEN_INTEGER ||
  578.                             tokenValue.integer < 0 ||
  579.                             tokenValue.integer > 255)
  580.                             return (SCAN_ERROR);
  581.                         i = tokenValue.integer;
  582.  
  583.                         /* get <characer_name> */
  584.                         scan_token(inputP);
  585.                         if (tokenType != TOKEN_LITERAL_NAME)
  586.                             return (SCAN_ERROR);
  587.  
  588.                         if (!(vm_alloc(tokenLength)))
  589.                             return (SCAN_OUT_OF_MEMORY);
  590.                         objFormatName(objP + i, tokenLength, tokenStartP);
  591.  
  592.                         /* get "put" */
  593.                         scan_token(inputP);
  594.                         if (tokenType != TOKEN_NAME)
  595.                             return (SCAN_ERROR);
  596.                     }
  597.                     else if (strncmp(tokenStartP, "def", 3) == 0)
  598.                         return (SCAN_OK);
  599.                 }
  600.                 break;
  601.             case TOKEN_EOF:
  602.             case TOKEN_NONE:
  603.             case TOKEN_INVALID:
  604.                 return (SCAN_ERROR);
  605.             }
  606.         }
  607.     }
  608.  
  609.     return (SCAN_ERROR);
  610. }
  611.  
  612.  
  613. /***================================================================***/
  614. static int getArray(psobj *arrayP)
  615. {
  616.     int N;            /* count the items in the array */
  617.     psobj *objP;
  618.  
  619.  
  620.     scan_token(inputP);
  621.     if ((tokenType != TOKEN_LEFT_BRACE) &&
  622.         (tokenType != TOKEN_LEFT_BRACKET))
  623.     {
  624.         return (SCAN_ERROR);
  625.     }
  626.     /* format the array in memory, save pointer to the beginning */
  627.     arrayP->data.valueP = tokenStartP;
  628.     /* loop, picking up next object, until right BRACE or BRACKET */
  629.     N = 0;
  630.     do
  631.     {
  632.         scan_token(inputP);
  633.         if ((tokenType == TOKEN_RIGHT_BRACE) ||
  634.             (tokenType == TOKEN_RIGHT_BRACKET))
  635.         {
  636.             /* save then number of items in the array */
  637.             arrayP->len = N;
  638.             return (SCAN_OK);
  639.         }
  640.         /* allocate the space for the object */
  641.         objP = (psobj *) vm_alloc(sizeof(psobj));
  642.         if (!(objP))
  643.             return (SCAN_OUT_OF_MEMORY);
  644.  
  645.         /* array is an array of numbers, (real or integer)  */
  646.         if (tokenType == TOKEN_REAL)
  647.         {
  648.             objFormatReal(objP, tokenValue.real);
  649.         }
  650.         else if (tokenType == TOKEN_INTEGER)
  651.         {
  652.             objFormatInteger(objP, tokenValue.integer);
  653.         }
  654.         else
  655.             return (SCAN_ERROR);
  656.         N++;
  657.     }
  658.     while (1 > 0);
  659.     /* NOTREACHED*/
  660. }
  661. /***================================================================***/
  662. static int getName(char *nameP)
  663. {
  664.     do
  665.     {
  666.         scan_token(inputP);
  667.         if (tokenType <= TOKEN_NONE)
  668.         {
  669.             if (tokenTooLong)
  670.                 return (SCAN_OUT_OF_MEMORY);
  671.             return (SCAN_ERROR);
  672.         }
  673.     }
  674.     while ((tokenType != TOKEN_NAME) ||
  675.            (0 != strncmp(tokenStartP, nameP, strlen(nameP))));
  676.     /* found */
  677.     return (SCAN_OK);
  678. }
  679. /***================================================================***/
  680. static int getNbytes(int N)
  681. {
  682.     int I;
  683.  
  684.  
  685.     tokenStartP = vm_next_byte();
  686.     tokenMaxP = tokenStartP + MIN(vm_free_bytes(), MAX_STRING_LEN);
  687.     if (N > vm_free_bytes())
  688.     {
  689.         return (SCAN_OUT_OF_MEMORY);
  690.     }
  691.     I = T1Read(tokenStartP, 1, N, inputP->data.fileP);
  692.     if (I != N)
  693.         return (SCAN_FILE_EOF);
  694.     return (SCAN_OK);
  695. }
  696.  
  697. /***================================================================***/
  698. /*  getLiteralName(nameObjP)                                          */
  699. /*     scan for next literal.                                         */
  700. /*  if we encounter the name 'end' then terminate and say ok.         */
  701. /*    It means that the CharStrings does not have as many characters  */
  702. /*    as the dictionary said it would and that is ok.                 */
  703. /***================================================================***/
  704. static int getLiteralName(psobj *nameObjP)
  705. {
  706.     do
  707.     {
  708.         scan_token(inputP);
  709.         if (tokenType <= TOKEN_NONE)
  710.         {
  711.             if (tokenTooLong)
  712.                 return (SCAN_OUT_OF_MEMORY);
  713.             return (SCAN_ERROR);
  714.         }
  715.         if (tokenType == TOKEN_NAME)
  716.         {
  717.             if (0 == strncmp(tokenStartP, "end", 3))
  718.             {
  719.                 return (SCAN_END);
  720.             }
  721.         }
  722.     }
  723.     while (tokenType != TOKEN_LITERAL_NAME);
  724.     nameObjP->len = tokenLength;
  725.     /* allocate all the names in the CharStrings Structure */
  726.     if (!(vm_alloc(tokenLength)))
  727.         return (SCAN_OUT_OF_MEMORY);
  728.     nameObjP->data.valueP = tokenStartP;
  729.     /* found */
  730.     return (SCAN_OK);
  731. }
  732.  
  733. /***================================================================***/
  734. /*
  735.  *   BuildSubrs routine
  736.  */
  737. /***================================================================***/
  738.  
  739. static int BuildSubrs(psfont *FontP)
  740. {
  741.     int N;            /* number of values in Subrs */
  742.     int I;            /* index into Subrs */
  743.     int i;            /* loop thru  Subrs */
  744.     int J;            /* length of Subrs entry */
  745.     psobj *arrayP;
  746.  
  747.     /* next token should be a positive int */
  748.     /* note: rc is set by getInt. */
  749.     N = getInt();
  750.     if (rc)
  751.         return (rc);
  752.     if (N < 0)
  753.         return (SCAN_ERROR);
  754.     /* if we already have a Subrs, then skip the second one */
  755.     /* The second one is for hiresolution devices.          */
  756.     if (FontP->Subrs.data.arrayP != NULL)
  757.     {
  758.         TwoSubrs = TRUE;
  759.         /* process all the Subrs, but do not update anything */
  760.         /* can not just skip them because of the binary data */
  761.         for (i = 0; i < N; i++)
  762.         {
  763.             /* look for dup */
  764.             rc = getName("dup");
  765.             if (rc)
  766.                 return (rc);
  767.             /* get 2 integers */
  768.             I = getInt();
  769.             if (rc)
  770.                 return (rc);
  771.             J = getInt();
  772.             if (rc)
  773.                 return (rc);
  774.             if ((I < 0) || (J < 0))
  775.                 return (SCAN_ERROR);
  776.             /* get the next token, it should be RD or -|, either is ok */
  777.             rc = getNextValue(TOKEN_NAME);
  778.             if (rc != SCAN_OK)
  779.                 return (rc);
  780.             rc = getNbytes(J);
  781.             if (rc)
  782.                 return (rc);
  783.         }
  784.         return (SCAN_OK);
  785.     }
  786.  
  787.     arrayP = (psobj *) vm_alloc(N * sizeof(psobj));
  788.     if (!(arrayP))
  789.         return (SCAN_OUT_OF_MEMORY);
  790.     FontP->Subrs.len = N;
  791.     FontP->Subrs.data.arrayP = arrayP;
  792.     /* get N values for Subrs */
  793.     for (i = 0; i < N; i++)
  794.     {
  795.         /* look for dup */
  796.         rc = getName("dup");
  797.         if (rc)
  798.             return (rc);
  799.         /* get 2 integers */
  800.         I = getInt();
  801.         if (rc)
  802.             return (rc);
  803.         J = getInt();
  804.         if (rc)
  805.             return (rc);
  806.         if ((I < 0) || (J < 0))
  807.             return (SCAN_ERROR);
  808.         arrayP[I].len = J;
  809.         /* get the next token, it should be RD or -|, either is ok */
  810.         rc = getNextValue(TOKEN_NAME);
  811.         if (rc != SCAN_OK)
  812.             return (rc);
  813.         rc = getNbytes(J);
  814.         if (rc == SCAN_OK)
  815.         {
  816.             arrayP[I].data.valueP = tokenStartP;
  817.             if (!(vm_alloc(J)))
  818.                 return (SCAN_OUT_OF_MEMORY);
  819.         }
  820.         else
  821.             return (rc);
  822.     }
  823.     return (SCAN_OK);
  824.  
  825. }
  826. /***================================================================***/
  827. /***================================================================***/
  828. /*
  829.  *   BuildCharStrings routine
  830.  */
  831. /***================================================================***/
  832.  
  833. static int BuildCharStrings(psfont *FontP)
  834. {
  835.     int N;            /* number of values in CharStrings */
  836.     int i;            /* loop thru  Subrs */
  837.     int J;            /* length of Subrs entry */
  838.     psdict *dictP;
  839.  
  840.     /* next token should be a positive int */
  841.     N = getInt();
  842.     if (rc)
  843.     {
  844.         /* check if file had TwoSubrs, hi resolution stuff is in file*/
  845.         if (TwoSubrs)
  846.         {
  847.             do
  848.             {
  849.                 scan_token(inputP);
  850.                 if (tokenType <= TOKEN_NONE)
  851.                 {
  852.                     if (tokenTooLong)
  853.                         return (SCAN_OUT_OF_MEMORY);
  854.                     return (SCAN_ERROR);
  855.                 }
  856.             }
  857.             while (tokenType != TOKEN_INTEGER);
  858.             N = tokenValue.integer;
  859.         }
  860.         else
  861.             return (rc);    /* if next token was not an Int */
  862.     }
  863.     if (N <= 0)
  864.         return (SCAN_ERROR);
  865.     /* save number of entries in the dictionary */
  866.  
  867.     dictP = (psdict *) vm_alloc((N + 1) * sizeof(psdict));
  868.     if (!(dictP))
  869.         return (SCAN_OUT_OF_MEMORY);
  870.     FontP->CharStringsP = dictP;
  871.     dictP[0].key.len = N;
  872.     /* get N values for CharStrings */
  873.     for (i = 1; i <= N; i++)
  874.     {
  875.         /* look for next literal name  */
  876.         rc = getLiteralName(&(dictP[i].key));
  877.         if (rc)
  878.             return (rc);
  879.         /* get 1 integer */
  880.         J = getInt();
  881.         if (rc)
  882.             return (rc);    /* if next token was not an Int */
  883.         if (J < 0)
  884.             return (SCAN_ERROR);
  885.         dictP[i].value.len = J;
  886.         /* get the next token, it should be RD or -|, either is ok */
  887.         rc = getNextValue(TOKEN_NAME);
  888.         if (rc != SCAN_OK)
  889.             return (rc);
  890.         rc = getNbytes(J);
  891.         if (rc == SCAN_OK)
  892.         {
  893.             dictP[i].value.data.valueP = tokenStartP;
  894.             if (!(vm_alloc(J)))
  895.                 return (SCAN_OUT_OF_MEMORY);
  896.         }
  897.         else
  898.             return (rc);
  899.     }
  900.     return (SCAN_OK);
  901.  
  902. }
  903. /***================================================================***/
  904. /***================================================================***/
  905. /*
  906.  *   BuildFontInfo Dictionary
  907.  */
  908. /***================================================================***/
  909. static int BuildFontInfo(psfont *fontP)
  910. {
  911.     psdict *dictP;
  912.  
  913.     /* allocate the private dictionary */
  914.     dictP = (psdict *) vm_alloc(20 * sizeof(psdict));
  915.     if (!(dictP))
  916.         return (SCAN_OUT_OF_MEMORY);
  917.  
  918.     fontP->fontInfoP = dictP;
  919.     fontP->fontInfoP[0].key.len = 17;    /* number of actual entries */
  920.     objFormatName(&(dictP[FONTNAME].key), 8, "FontName");
  921.     objFormatName(&(dictP[FONTNAME].value), 0, NULL);
  922.     objFormatName(&(dictP[PAINTTYPE].key), 9, "PaintType");
  923.     objFormatInteger(&(dictP[PAINTTYPE].value), 0);
  924.     objFormatName(&(dictP[FONTTYPENUM].key), 8, "FontType");
  925.     objFormatInteger(&(dictP[FONTTYPENUM].value), 0);
  926.     objFormatName(&(dictP[FONTMATRIX].key), 10, "FontMatrix");
  927.     objFormatArray(&(dictP[FONTMATRIX].value), 0, NULL);
  928.     objFormatName(&(dictP[FONTBBOX].key), 8, "FontBBox");
  929.     objFormatArray(&(dictP[FONTBBOX].value), 0, NULL);
  930.     objFormatName(&(dictP[ENCODING].key), 8, "Encoding");
  931.     objFormatEncoding(&(dictP[ENCODING].value), 0, NULL);
  932.     objFormatName(&(dictP[UNIQUEID].key), 8, "UniqueID");
  933.     objFormatInteger(&(dictP[UNIQUEID].value), 0);
  934.     objFormatName(&(dictP[STROKEWIDTH].key), 11, "StrokeWidth");
  935.     objFormatReal(&(dictP[STROKEWIDTH].value), 0.0);
  936.     objFormatName(&(dictP[VERSION].key), 7, "version");
  937.     objFormatString(&(dictP[VERSION].value), 0, NULL);
  938.     objFormatName(&(dictP[NOTICE].key), 6, "Notice");
  939.     objFormatString(&(dictP[NOTICE].value), 0, NULL);
  940.     objFormatName(&(dictP[FULLNAME].key), 8, "FullName");
  941.     objFormatString(&(dictP[FULLNAME].value), 0, NULL);
  942.     objFormatName(&(dictP[FAMILYNAME].key), 10, "FamilyName");
  943.     objFormatString(&(dictP[FAMILYNAME].value), 0, NULL);
  944.     objFormatName(&(dictP[WEIGHT].key), 6, "Weight");
  945.     objFormatString(&(dictP[WEIGHT].value), 0, NULL);
  946.     objFormatName(&(dictP[ITALICANGLE].key), 11, "ItalicAngle");
  947.     objFormatReal(&(dictP[ITALICANGLE].value), 0.0);
  948.     objFormatName(&(dictP[ISFIXEDPITCH].key), 12, "isFixedPitch");
  949.     objFormatBoolean(&(dictP[ISFIXEDPITCH].value), FALSE);
  950.     objFormatName(&(dictP[UNDERLINEPOSITION].key), 17, "UnderlinePosition");
  951.     objFormatReal(&(dictP[UNDERLINEPOSITION].value), 0.0);
  952.     objFormatName(&(dictP[UNDERLINETHICKNESS].key), 18, "UnderlineThickness");
  953.     objFormatReal(&(dictP[UNDERLINETHICKNESS].value), 0.0);
  954.     return (SCAN_OK);
  955. }
  956. /***================================================================***/
  957. /*
  958.  *   BuildPrivate Dictionary
  959.  */
  960. /***================================================================***/
  961. static int BuildPrivate(psfont *fontP)
  962. {
  963.     psdict *Private;
  964.  
  965.     /* allocate the private dictionary */
  966.     Private = (psdict *) vm_alloc(20 * sizeof(psdict));
  967.  
  968.     if (!(Private))
  969.         return (SCAN_OUT_OF_MEMORY);
  970.  
  971.     fontP->Private = Private;
  972.     fontP->Private[0].key.len = 16;    /* number of actual entries */
  973.  
  974.     objFormatName(&(Private[BLUEVALUES].key), 10, "BlueValues");
  975.     objFormatArray(&(Private[BLUEVALUES].value), 0, NULL);
  976.     objFormatName(&(Private[OTHERBLUES].key), 10, "OtherBlues");
  977.     objFormatArray(&(Private[OTHERBLUES].value), 0, NULL);
  978.     objFormatName(&(Private[FAMILYBLUES].key), 11, "FamilyBlues");
  979.     objFormatArray(&(Private[FAMILYBLUES].value), 0, NULL);
  980.     objFormatName(&(Private[FAMILYOTHERBLUES].key), 16, "FamilyOtherBlues");
  981.     objFormatArray(&(Private[FAMILYOTHERBLUES].value), 0, NULL);
  982.     objFormatName(&(Private[BLUESCALE].key), 9, "BlueScale");
  983.     objFormatReal(&(Private[BLUESCALE].value), DEFAULTBLUESCALE);
  984.     objFormatName(&(Private[BLUESHIFT].key), 9, "BlueShift");
  985.     objFormatInteger(&(Private[BLUESHIFT].value), DEFAULTBLUESHIFT);
  986.     objFormatName(&(Private[BLUEFUZZ].key), 8, "BlueFuzz");
  987.     objFormatInteger(&(Private[BLUEFUZZ].value), DEFAULTBLUEFUZZ);
  988.     objFormatName(&(Private[STDHW].key), 5, "StdHW");
  989.     objFormatArray(&(Private[STDHW].value), 0, NULL);
  990.     objFormatName(&(Private[STDVW].key), 5, "StdVW");
  991.     objFormatArray(&(Private[STDVW].value), 0, NULL);
  992.     objFormatName(&(Private[STEMSNAPH].key), 9, "StemSnapH");
  993.     objFormatArray(&(Private[STEMSNAPH].value), 0, NULL);
  994.     objFormatName(&(Private[STEMSNAPV].key), 9, "StemSnapV");
  995.     objFormatArray(&(Private[STEMSNAPV].value), 0, NULL);
  996.     objFormatName(&(Private[FORCEBOLD].key), 9, "ForceBold");
  997.     objFormatBoolean(&(Private[FORCEBOLD].value), DEFAULTFORCEBOLD);
  998.     objFormatName(&(Private[LANGUAGEGROUP].key), 13, "LanguageGroup");
  999.     objFormatInteger(&(Private[LANGUAGEGROUP].value), DEFAULTLANGUAGEGROUP);
  1000.     objFormatName(&(Private[LENIV].key), 5, "LenIV");
  1001.     objFormatInteger(&(Private[LENIV].value), DEFAULTLENIV);
  1002.     objFormatName(&(Private[RNDSTEMUP].key), 9, "RndStemUp");
  1003.     objFormatBoolean(&(Private[RNDSTEMUP].value), DEFAULTRNDSTEMUP);
  1004.     objFormatName(&(Private[EXPANSIONFACTOR].key), 9, "ExpansionFactor");
  1005.     objFormatReal(&(Private[EXPANSIONFACTOR].value),
  1006.               DEFAULTEXPANSIONFACTOR);
  1007.     return (SCAN_OK);
  1008. }
  1009. /***================================================================***/
  1010. /**********************************************************************/
  1011. /*     GetType1Blues(fontP)                                           */
  1012. /*                                                                    */
  1013. /*   Routine to support font-level hints.                             */
  1014. /*                                                                    */
  1015. /*         Gets all the Blues information from the Private dictionary */
  1016. /*         for the font.                                              */
  1017. /*                                                                    */
  1018. /*                                                                    */
  1019. /**********************************************************************/
  1020. static int GetType1Blues(psfont *fontP)
  1021. {
  1022.     psdict *PrivateDictP;    /* the Private dict relating to hints */
  1023.     struct blues_struct *blues;    /* ptr for the blues struct we will allocate */
  1024.     int i;
  1025.     psobj *HintEntryP;
  1026.  
  1027.  
  1028.  
  1029.     /* get the Private dictionary pointer */
  1030.     PrivateDictP = fontP->Private;
  1031.  
  1032.     /* allocate the memory for the blues structure */
  1033.     blues = (struct blues_struct *)vm_alloc(sizeof(struct blues_struct));
  1034.  
  1035.     if (!blues)
  1036.         return (SCAN_OUT_OF_MEMORY);
  1037.  
  1038.     /* Make fontP's blues ptr point to this newly allocated structure. */
  1039.     fontP->BluesP = blues;
  1040.  
  1041.     /* fill in the BlueValues array */
  1042.     HintEntryP = &(PrivateDictP[BLUEVALUES].value);
  1043.     /* check to see if the entry exists and if it's an array */
  1044.     if (!objPIsArray(HintEntryP) || (HintEntryP->len == 0))
  1045.         blues->numBlueValues = 0;
  1046.     else
  1047.     {
  1048.         /* get the number of values in the array */
  1049.         if (HintEntryP->len > NUMBLUEVALUES)
  1050.         {
  1051.             blues->numBlueValues = NUMBLUEVALUES;
  1052.         }
  1053.         else
  1054.             blues->numBlueValues = HintEntryP->len;
  1055.         for (i = 0; i <= blues->numBlueValues - 1; ++i)
  1056.         {
  1057.             if (objPIsInteger(&HintEntryP->data.arrayP[i]))
  1058.                 blues->BlueValues[i] =
  1059.                     HintEntryP->data.arrayP[i].data.integer;
  1060.             else if (objPIsReal(&HintEntryP->data.arrayP[i]))
  1061.                 blues->BlueValues[i] =
  1062.                     HintEntryP->data.arrayP[i].data.real;
  1063.             else
  1064.                 blues->BlueValues[i] = 0;
  1065.         }
  1066.     }
  1067.  
  1068.     /* fill in the OtherBlues array */
  1069.     HintEntryP = &(PrivateDictP[OTHERBLUES].value);
  1070.     /* check to see if the entry exists and if it's an array */
  1071.     if (!objPIsArray(HintEntryP) || (HintEntryP->len == 0))
  1072.         blues->numOtherBlues = 0;
  1073.     else
  1074.     {
  1075.         /* get the number of values in the array */
  1076.         if (HintEntryP->len > NUMOTHERBLUES)
  1077.         {
  1078.             blues->numOtherBlues = NUMOTHERBLUES;
  1079.         }
  1080.         else
  1081.             blues->numOtherBlues = HintEntryP->len;
  1082.         for (i = 0; i <= blues->numOtherBlues - 1; ++i)
  1083.         {
  1084.             if (objPIsInteger(&HintEntryP->data.arrayP[i]))
  1085.                 blues->OtherBlues[i] =
  1086.                     HintEntryP->data.arrayP[i].data.integer;
  1087.             else if (objPIsReal(&HintEntryP->data.arrayP[i]))
  1088.                 blues->OtherBlues[i] =
  1089.                     HintEntryP->data.arrayP[i].data.real;
  1090.             else
  1091.                 blues->OtherBlues[i] = 0;
  1092.         }
  1093.     }
  1094.  
  1095.     /* fill in the FamilyBlues array */
  1096.     HintEntryP = &(PrivateDictP[FAMILYBLUES].value);
  1097.     /* check to see if the entry exists and if it's an array */
  1098.     if (!objPIsArray(HintEntryP) || (HintEntryP->len == 0))
  1099.         blues->numFamilyBlues = 0;
  1100.     else
  1101.     {
  1102.         /* get the number of values in the array */
  1103.         if (HintEntryP->len > NUMFAMILYBLUES)
  1104.         {
  1105.             blues->numFamilyBlues = NUMFAMILYBLUES;
  1106.         }
  1107.         else
  1108.             blues->numFamilyBlues = HintEntryP->len;
  1109.         for (i = 0; i <= blues->numFamilyBlues - 1; ++i)
  1110.         {
  1111.             if (objPIsInteger(&HintEntryP->data.arrayP[i]))
  1112.                 blues->FamilyBlues[i] =
  1113.                     HintEntryP->data.arrayP[i].data.integer;
  1114.             else if (objPIsReal(&HintEntryP->data.arrayP[i]))
  1115.                 blues->FamilyBlues[i] =
  1116.                     HintEntryP->data.arrayP[i].data.real;
  1117.             else
  1118.                 blues->FamilyBlues[i] = 0;
  1119.         }
  1120.     }
  1121.  
  1122.     /* fill in the FamilyOtherBlues array */
  1123.     HintEntryP = &(PrivateDictP[FAMILYOTHERBLUES].value);
  1124.     /* check to see if the entry exists and if it's an array */
  1125.     if (!objPIsArray(HintEntryP) || (HintEntryP->len == 0))
  1126.         blues->numFamilyOtherBlues = 0;
  1127.     else
  1128.     {
  1129.         /* get the number of values in the array */
  1130.         if (HintEntryP->len > NUMFAMILYOTHERBLUES)
  1131.         {
  1132.             blues->numFamilyOtherBlues = NUMFAMILYOTHERBLUES;
  1133.         }
  1134.         else
  1135.             blues->numFamilyOtherBlues = HintEntryP->len;
  1136.         for (i = 0; i <= blues->numFamilyOtherBlues - 1; ++i)
  1137.         {
  1138.             if (objPIsInteger(&HintEntryP->data.arrayP[i]))
  1139.                 blues->FamilyOtherBlues[i] =
  1140.                     HintEntryP->data.arrayP[i].data.integer;
  1141.             else if (objPIsReal(&HintEntryP->data.arrayP[i]))
  1142.                 blues->FamilyOtherBlues[i] =
  1143.                     HintEntryP->data.arrayP[i].data.real;
  1144.             else
  1145.                 blues->FamilyOtherBlues[i] = 0;
  1146.         }
  1147.     }
  1148.  
  1149.     /* fill in the StemSnapH array */
  1150.     HintEntryP = &(PrivateDictP[STEMSNAPH].value);
  1151.     /* check to see if the entry exists and if it's an array */
  1152.     if (!objPIsArray(HintEntryP) || (HintEntryP->len == 0))
  1153.         blues->numStemSnapH = 0;
  1154.     else
  1155.     {
  1156.         /* get the number of values in the array */
  1157.         if (HintEntryP->len > NUMSTEMSNAPH)
  1158.         {
  1159.             blues->numStemSnapH = NUMSTEMSNAPH;
  1160.         }
  1161.         else
  1162.             blues->numStemSnapH = HintEntryP->len;
  1163.         for (i = 0; i <= blues->numStemSnapH - 1; ++i)
  1164.         {
  1165.             if (objPIsInteger(&HintEntryP->data.arrayP[i]))
  1166.                 blues->StemSnapH[i] =
  1167.                     HintEntryP->data.arrayP[i].data.integer;
  1168.             else if (objPIsReal(&HintEntryP->data.arrayP[i]))
  1169.                 blues->StemSnapH[i] =
  1170.                     HintEntryP->data.arrayP[i].data.real;
  1171.             else
  1172.                 blues->StemSnapH[i] = 0;
  1173.         }
  1174.     }
  1175.  
  1176.     /* fill in the StemSnapV array */
  1177.     HintEntryP = &(PrivateDictP[STEMSNAPV].value);
  1178.     /* check to see if the entry exists and if it's an array */
  1179.     if (!objPIsArray(HintEntryP) || (HintEntryP->len == 0))
  1180.         blues->numStemSnapV = 0;
  1181.     else
  1182.     {
  1183.         /* get the number of values in the array */
  1184.         if (HintEntryP->len > NUMSTEMSNAPV)
  1185.         {
  1186.             blues->numStemSnapV = NUMSTEMSNAPV;
  1187.         }
  1188.         else
  1189.             blues->numStemSnapV = HintEntryP->len;
  1190.         for (i = 0; i <= blues->numStemSnapV - 1; ++i)
  1191.         {
  1192.             if (objPIsInteger(&HintEntryP->data.arrayP[i]))
  1193.                 blues->StemSnapV[i] =
  1194.                     HintEntryP->data.arrayP[i].data.integer;
  1195.             else if (objPIsReal(&HintEntryP->data.arrayP[i]))
  1196.                 blues->StemSnapV[i] =
  1197.                     HintEntryP->data.arrayP[i].data.real;
  1198.             else
  1199.                 blues->StemSnapV[i] = 0;
  1200.         }
  1201.     }
  1202.  
  1203.     /* fill in the StdVW array */
  1204.     HintEntryP = &(PrivateDictP[STDVW].value);
  1205.     /* check to see if the entry exists and if it's an array */
  1206.     if (!objPIsArray(HintEntryP) || (HintEntryP->len == 0))
  1207.         /* a value of zero signifies no entry */
  1208.         blues->StdVW = 0;
  1209.     else
  1210.     {
  1211.         if (HintEntryP->len > NUMSTDVW)
  1212.         {
  1213.         }
  1214.         if (objPIsInteger(&HintEntryP->data.arrayP[0]))
  1215.             blues->StdVW = HintEntryP->data.arrayP[0].data.integer;
  1216.         else if (objPIsReal(&HintEntryP->data.arrayP[0]))
  1217.             blues->StdVW = HintEntryP->data.arrayP[0].data.real;
  1218.         else
  1219.             blues->StdVW = 0;
  1220.     }
  1221.  
  1222.     /* fill in the StdHW array */
  1223.     HintEntryP = &(PrivateDictP[STDHW].value);
  1224.     /* check to see if the entry exists and if it's an array */
  1225.     if (!objPIsArray(HintEntryP) || (HintEntryP->len == 0))
  1226.         /* a value of zero signifies no entry */
  1227.         blues->StdHW = 0;
  1228.     else
  1229.     {
  1230.         if (HintEntryP->len > NUMSTDHW)
  1231.         {
  1232.         }
  1233.         if (objPIsInteger(&HintEntryP->data.arrayP[0]))
  1234.             blues->StdHW = HintEntryP->data.arrayP[0].data.integer;
  1235.         else if (objPIsReal(&HintEntryP->data.arrayP[0]))
  1236.             blues->StdHW = HintEntryP->data.arrayP[0].data.real;
  1237.         else
  1238.             blues->StdHW = 0;
  1239.     }
  1240.  
  1241.  
  1242.     /* get the ptr to the BlueScale entry */
  1243.     HintEntryP = &(PrivateDictP[BLUESCALE].value);
  1244.     /* put the BlueScale in the blues structure */
  1245.     if (objPIsInteger(HintEntryP))    /* Must be integer! */
  1246.         blues->BlueScale = HintEntryP->data.integer;
  1247.     else if (objPIsReal(HintEntryP))    /* Error? */
  1248.         blues->BlueScale = HintEntryP->data.real;
  1249.     else
  1250.         blues->BlueScale = DEFAULTBLUESCALE;
  1251.  
  1252.     /* get the ptr to the BlueShift entry */
  1253.     HintEntryP = &(PrivateDictP[BLUESHIFT].value);
  1254.     if (objPIsInteger(HintEntryP))    /* Must be integer! */
  1255.         blues->BlueShift = HintEntryP->data.integer;
  1256.     else if (objPIsReal(HintEntryP))    /* Error? */
  1257.         blues->BlueShift = HintEntryP->data.real;
  1258.     else
  1259.         blues->BlueShift = DEFAULTBLUESHIFT;
  1260.  
  1261.     /* get the ptr to the BlueFuzz entry */
  1262.     HintEntryP = &(PrivateDictP[BLUEFUZZ].value);
  1263.     if (objPIsInteger(HintEntryP))    /* Must be integer! */
  1264.         blues->BlueFuzz = HintEntryP->data.integer;
  1265.     else if (objPIsReal(HintEntryP))    /* Error? */
  1266.         blues->BlueFuzz = HintEntryP->data.real;
  1267.     else
  1268.         blues->BlueFuzz = DEFAULTBLUEFUZZ;
  1269.  
  1270.     /* get the ptr to the ForceBold entry */
  1271.     HintEntryP = &(PrivateDictP[FORCEBOLD].value);
  1272.     if (objPIsBoolean(HintEntryP))    /* Must be integer! */
  1273.         blues->ForceBold = HintEntryP->data.boolean;
  1274.     else
  1275.         blues->ForceBold = DEFAULTFORCEBOLD;
  1276.  
  1277.     /* get the ptr to the LanguageGroup entry */
  1278.     HintEntryP = &(PrivateDictP[LANGUAGEGROUP].value);
  1279.     if (objPIsInteger(HintEntryP))    /* Must be integer! */
  1280.         blues->LanguageGroup = HintEntryP->data.integer;
  1281.     else
  1282.         blues->LanguageGroup = DEFAULTLANGUAGEGROUP;
  1283.  
  1284.     /* get the ptr to the RndStemUp entry */
  1285.     HintEntryP = &(PrivateDictP[RNDSTEMUP].value);
  1286.     if (objPIsBoolean(HintEntryP))    /* Must be integer! */
  1287.         blues->RndStemUp = HintEntryP->data.boolean;
  1288.     else
  1289.         blues->RndStemUp = DEFAULTRNDSTEMUP;
  1290.  
  1291.     /* get the ptr to the lenIV entry */
  1292.     HintEntryP = &(PrivateDictP[LENIV].value);
  1293.     if (objPIsInteger(HintEntryP))    /* Must be integer! */
  1294.         blues->lenIV = HintEntryP->data.integer;
  1295.     else
  1296.         blues->lenIV = DEFAULTLENIV;
  1297.  
  1298.     /* get the ptr to the ExpansionFactor entry */
  1299.     HintEntryP = &(PrivateDictP[EXPANSIONFACTOR].value);
  1300.     if (objPIsInteger(HintEntryP))
  1301.         blues->ExpansionFactor = HintEntryP->data.integer;
  1302.     else if (objPIsReal(HintEntryP))
  1303.         blues->ExpansionFactor = HintEntryP->data.real;
  1304.     else
  1305.         blues->ExpansionFactor = DEFAULTEXPANSIONFACTOR;
  1306.     return (SCAN_OK);
  1307. }
  1308. /**********************************************************************/
  1309. /*   GetType1CharString(fontP,code)                                   */
  1310. /*                                                                    */
  1311. /*          Look up code in the standard encoding vector and return   */
  1312. /*          the charstring associated with the character name.        */
  1313. /*                                                                    */
  1314. /*   fontP  is the psfont structure.                                  */
  1315. /*                                                                    */
  1316. /*   Returns a psobj (string)                                         */
  1317. /**********************************************************************/
  1318. psobj *GetType1CharString(psfont *fontP, unsigned char code)
  1319. {
  1320.     int N;            /* the 'Nth' entry in the CharStrings       */
  1321.     psobj *charnameP;    /* points to psobj that is name of character*/
  1322.  
  1323.     psdict *CharStringsDictP;    /* dictionary with char strings     */
  1324.     psobj *theStringP;    /* the definition for the code */
  1325.  
  1326.  
  1327.  
  1328.     if (StdEncArrayP == NULL)
  1329.     {
  1330.         return (NULL);
  1331.     }
  1332.     /* use the code to index into the standard encoding vector  */
  1333.     charnameP = &(StdEncArrayP[code]);
  1334.  
  1335.     /* test if the encoding array points to a name */
  1336.     if (!(objPIsName(charnameP)))
  1337.     {
  1338.         return (NULL);
  1339.     }
  1340.  
  1341.     /* Now that we have the character name out of the standardencoding */
  1342.     /* get the character definition out of the current font */
  1343.     CharStringsDictP = fontP->CharStringsP;
  1344.  
  1345.     /* search the chars string for this charname as key */
  1346.     N = SearchDictName(CharStringsDictP, charnameP);
  1347.     if (N <= 0)
  1348.     {
  1349.         return (NULL);
  1350.     }
  1351.     /* OK, the nth item is the psobj that is the string for this char */
  1352.     theStringP = &(CharStringsDictP[N].value);
  1353.  
  1354.     return (theStringP);
  1355. }
  1356.  
  1357. /***================================================================***/
  1358. /*
  1359.  *   FindDictValue
  1360.  */
  1361. /***================================================================***/
  1362.  
  1363. static int FindDictValue(psdict *dictP)
  1364. {
  1365.     psobj LitName;
  1366.     int N;
  1367.     int V;
  1368.  
  1369.     /* we have just scanned a token and it is a literal name */
  1370.     /* need to check if that name is in Private dictionary */
  1371.     objFormatName(&LitName, tokenLength, tokenStartP);
  1372.     /* is it in the dictP */
  1373.     N = SearchDictName(dictP, &LitName);
  1374.     /* if found */
  1375.     if (N > 0)
  1376.     {
  1377.         /* what type */
  1378.         switch (dictP[N].value.type)
  1379.         {
  1380.         case OBJ_ENCODING:
  1381.             V = getEncoding(&(dictP[N].value));
  1382.             if (V != SCAN_OK)
  1383.                 return (V);
  1384.             break;
  1385.         case OBJ_ARRAY:
  1386.             V = getArray(&(dictP[N].value));
  1387.             if (V != SCAN_OK)
  1388.                 return (V);
  1389.             break;
  1390.         case OBJ_INTEGER:
  1391.             /* next value in integer */
  1392.             dictP[N].value.data.integer = getInt();
  1393.             if (rc)
  1394.                 return (rc);    /* if next token was not an Int */
  1395.             break;
  1396.         case OBJ_REAL:
  1397.             /* next value must be real or int, store as a real */
  1398.             scan_token(inputP);
  1399.             if (tokenType == TOKEN_REAL)
  1400.             {
  1401.                 dictP[N].value.data.real = tokenValue.real;
  1402.             }
  1403.             else if (tokenType == TOKEN_INTEGER)
  1404.             {
  1405.                 dictP[N].value.data.real = tokenValue.integer;
  1406.             }
  1407.             else
  1408.                 return (SCAN_ERROR);
  1409.             break;
  1410.         case OBJ_NAME:
  1411.             V = getNextValue(TOKEN_LITERAL_NAME);
  1412.             if (V != SCAN_OK)
  1413.                 return (V);
  1414.             if (!(vm_alloc(tokenLength+1)))
  1415.                 return (SCAN_OUT_OF_MEMORY);
  1416.             objFormatName(&(dictP[N].value), tokenLength, tokenStartP);
  1417.             break;
  1418.         case OBJ_STRING:
  1419.             V = getNextValue(TOKEN_STRING);
  1420.             if (V != SCAN_OK)
  1421.                 return (V);
  1422.             if (!(vm_alloc(tokenLength)))
  1423.                 return (SCAN_OUT_OF_MEMORY);
  1424.             objFormatString(&(dictP[N].value), tokenLength, tokenStartP);
  1425.             break;
  1426.         case OBJ_BOOLEAN:
  1427.             scan_token(inputP);
  1428.             if (tokenType != TOKEN_NAME)
  1429.             {
  1430.                 return (SCAN_ERROR);
  1431.             }
  1432.             if (0 == strncmp(tokenStartP, "true", 4))
  1433.             {
  1434.                 dictP[N].value.data.boolean = TRUE;
  1435.             }
  1436.             else if (0 == strncmp(tokenStartP, "false", 5))
  1437.             {
  1438.                 dictP[N].value.data.boolean = FALSE;
  1439.             }
  1440.             else
  1441.                 return (SCAN_ERROR);
  1442.             break;
  1443.  
  1444.         default:
  1445.             return (SCAN_ERROR);
  1446.             break;
  1447.         }
  1448.     }
  1449.     /* Name is not in dictionary.  That is ok. */
  1450.     return (SCAN_OK);
  1451.  
  1452. }
  1453. /***================================================================***/
  1454.  
  1455. /*
  1456.  * -------------------------------------------------------------------
  1457.  *  Scan the next token and convert it into an object
  1458.  *  Result is placed on the Operand Stack as next object
  1459.  * -------------------------------------------------------------------
  1460.  */
  1461. int scan_font(psfont *FontP)
  1462. {
  1463.     char filename[128];
  1464.     char filetype[3];
  1465.     F_FILE *fileP;
  1466.     const char *nameP;
  1467.     int namelen;
  1468.     int V;
  1469.     int i;
  1470.     boolean starthex80;
  1471.  
  1472.     starthex80 = FALSE;
  1473.     filetype[0] = 'r';
  1474. //    filetype[1] = 'b';
  1475. //    filetype[2] = '\0';
  1476.     filetype[1] = '\0';
  1477.     /* copy the filename and remove leading or trailing blanks */
  1478.     /* point to name and search for leading blanks */
  1479.     nameP = FontP->FontFileName.data.nameP;
  1480.     namelen = FontP->FontFileName.len;
  1481.     while (nameP[0] == ' ')
  1482.     {
  1483.         nameP++;
  1484.         namelen--;
  1485.     }
  1486.     /* now remove any trailing blanks */
  1487.     while ((namelen > 0) && (nameP[namelen - 1] == ' '))
  1488.     {
  1489.         namelen--;
  1490.     }
  1491.     strncpy(filename, nameP, namelen);
  1492.     filename[namelen] = '\0';
  1493.     /* file name is now constructed */
  1494.     inputFile.data.fileP = NULL;
  1495.     filterFile.data.fileP = NULL;
  1496.  
  1497.     inputP = &inputFile;
  1498.     if (fileP = T1Open(filename, filetype))
  1499.     {
  1500.         /* get the first byte of file */
  1501.         V = T1getc(fileP);
  1502.         /* if file starts with x'80' then skip next 5 bytes */
  1503.         if (V == 0X80)
  1504.         {
  1505.             for (i = 0; i < 5; i++)
  1506.                 T1getc(fileP);
  1507. //                V = T1getc(fileP);
  1508.             starthex80 = TRUE;
  1509.         }
  1510.         else
  1511.             T1ungetc(V, fileP);
  1512.         objFormatFile(inputP, fileP);
  1513.     }
  1514.     else
  1515.     {
  1516.         return (SCAN_FILE_OPEN_ERROR);
  1517.     };
  1518.  
  1519.     WantFontInfo = TRUE;
  1520.     InPrivateDict = FALSE;
  1521.     TwoSubrs = FALSE;
  1522.     rc = BuildFontInfo(FontP);
  1523.     if (rc != 0)
  1524.         return (rc);
  1525.  
  1526.     /* Assume everything will be OK */
  1527.     rc = 0;
  1528.  
  1529.     /* Loop until complete font is read  */
  1530.     do
  1531.     {
  1532.         /* Scan the next token */
  1533.         scan_token(inputP);
  1534.  
  1535.         /* ==> tokenLength, tokenTooLong, tokenType, and tokenValue are */
  1536.         /* now set */
  1537.  
  1538.         switch (tokenType)
  1539.         {
  1540.         case TOKEN_EOF:
  1541.         case TOKEN_NONE:
  1542.         case TOKEN_INVALID:
  1543.             /* in this case we are done */
  1544.             if (tokenTooLong)
  1545.                 return (SCAN_OUT_OF_MEMORY);
  1546.             rc = SCAN_ERROR;
  1547.             break;
  1548.         case TOKEN_LITERAL_NAME:
  1549.             /* Look up the name */
  1550.             tokenStartP[tokenLength] = '\0';
  1551.             if (InPrivateDict)
  1552.             {
  1553.                 if (0 == strncmp(tokenStartP, "Subrs", 5))
  1554.                 {
  1555.                     rc = BuildSubrs(FontP);
  1556.                     break;
  1557.                 }
  1558.                 if (0 == strncmp(tokenStartP, "CharStrings", 11))
  1559.                 {
  1560.                     rc = BuildCharStrings(FontP);
  1561.                     if ((rc == SCAN_OK) || (rc == SCAN_END))
  1562.                     {
  1563.                         T1Close(inputP->data.fileP);
  1564.                         /* Build the Blues Structure */
  1565.                         rc = GetType1Blues(FontP);
  1566.                         /* whatever the return code, return it */
  1567.                         /* all the work is done. This is the normal exit.*/
  1568.                         return (rc);
  1569.                     }
  1570.                     break;
  1571.                 }
  1572. //                rc = FindDictValue(FontP->Private);
  1573.                 FindDictValue(FontP->Private);
  1574.                 /* we are not going to report errors */
  1575.                 /* Sometimes the font file may test a value such as */
  1576.                 /* testing to see if the font is alreadly loaded with */
  1577.                 /* same UniqueID.  We would faile on /UniqueID get  */
  1578.                 /* because we are expecting a int to follow UniqueID*/
  1579.                 /* If the correct object type does not follow a Name*/
  1580.                 /* then we will skip over it without reporting error*/
  1581.                 rc = SCAN_OK;
  1582.                 break;
  1583.             }    /* end of reading Private dictionary */
  1584.             else if (0 == strncmp(tokenStartP, "Private", 7))
  1585.             {
  1586.                 InPrivateDict = TRUE;
  1587.                 rc = BuildPrivate(FontP);
  1588.                 break;
  1589.             }
  1590.             else if (WantFontInfo)
  1591.             {
  1592. //                rc = FindDictValue(FontP->fontInfoP);
  1593.                 FindDictValue(FontP->fontInfoP);
  1594.                 /* we are not going to report errors */
  1595.                 rc = SCAN_OK;
  1596.                 break;
  1597.             }
  1598.             break;
  1599.         case TOKEN_NAME:
  1600.             if (0 == strncmp(tokenStartP, "eexec", 5))
  1601.             {
  1602.                 /* if file started with x'80', check next 5 bytes */
  1603.                 if (starthex80)
  1604.                 {
  1605.                     V = T1getc(fileP);
  1606.                     if (V == 0X80)
  1607.                     {
  1608.                         for (i = 0; i < 5; i++)
  1609.                             T1getc(fileP);
  1610. //                            V = T1getc(fileP);
  1611.                     }
  1612.                     else
  1613.                         T1ungetc(V, fileP);
  1614.                 }
  1615.                 filterFile.data.fileP = inputP->data.fileP;
  1616.                 T1eexec(inputP->data.fileP);
  1617.                 if (filterFile.data.fileP == NULL)
  1618.                 {
  1619.                     T1Close(inputFile.data.fileP);
  1620.                     return (SCAN_FILE_OPEN_ERROR);
  1621.                 }
  1622.                 inputP = &filterFile;
  1623.  
  1624.                 WantFontInfo = FALSE;
  1625.             }
  1626.             break;
  1627.         }
  1628.  
  1629.     } while (rc == 0);
  1630.  
  1631.     T1Close(inputP->data.fileP);
  1632.     if (tokenTooLong)
  1633.         return (SCAN_OUT_OF_MEMORY);
  1634.     return (rc);
  1635. }
  1636.